use crate::common::file_io::get_ddl;
use crate::common::variables::update_project_base_dir;
use crate::db::connector::{get_connection, setup_database};
use crate::error::AppError;
use sea_orm::{ConnectionTrait, DatabaseConnection, Statement};
use std::path::Path;

/// 检查项目配置数据库是否存在 (单步骤拆分)
async fn check_exit(base_dir: &String) -> Result<bool, AppError> {
    // 检查 config.db是否存在, 若不存在则返回 false
    let db_path = Path::new(base_dir).join("config.db");
    if !db_path.exists() {
        return Ok(false);
    }

    Ok(true)
}

/// 检查相关表格是否存在 (单步骤拆分)
async fn check_base_tables(tables: Vec<&str>) -> Result<bool, AppError> {
    //  检查相关表是否存在（datasource/relation/...），若有一个不存在就返回 false
    let db = get_connection("project")?;
    for table in tables {
        let stmt = format!(
            "SELECT 1 FROM sqlite_master WHERE type='table' AND name='{}'",
            table
        );
        let statement = Statement::from_string(db.get_database_backend(), stmt);
        let table = db.query_one(statement).await?;
        if table.is_none() {
            return Ok(false);
        }
    }

    Ok(true) // 通过所有检测
}

/// 检查完整流程
pub async fn check_full(base_dir: &String) -> Result<bool, AppError> {
    // 检查配置数据库路径
    let first_check = check_exit(base_dir).await?;
    if !first_check {
        return Ok(false);
    }
    // 注册数据库
    create_or_load(base_dir).await?;
    // 检查相关表格
    let second_check =
        check_base_tables(vec!["ds_core", "ds_file", "ds_serve", "ds_description"]).await?;
    if !second_check {
        return Ok(false);
    }
    Ok(true)
}

/// 加载项目 (单步骤拆分)
async fn create_or_load(base_dir: &String) -> Result<(), AppError> {
    // 创建或加载数据库
    let db_path = format!("sqlite:{}/config.db?mode=rwc", base_dir);
    setup_database("project", db_path.as_str()).await?;
    Ok(())
}

/// 初始化项目 (单步骤拆分)
async fn init_step() -> Result<(), AppError> {
    // 取得数据库连接
    let db = get_connection("project")?;

    async fn _execute_sql(sql: &str, db: &DatabaseConnection) -> Result<(), AppError> {
        db.execute(Statement::from_string(db.get_database_backend(), sql))
            .await?;
        Ok(())
    }

    // ds_core
    let ds_core_sql = get_ddl("project-ds-core")?;
    _execute_sql(ds_core_sql.as_str(), &db).await?;
    // ds_file
    let ds_file_sql = get_ddl("project-ds-file")?;
    _execute_sql(ds_file_sql.as_str(), &db).await?;
    // ds_serve
    let ds_serve_sql = get_ddl("project-ds-serve")?;
    _execute_sql(ds_serve_sql.as_str(), &db).await?;
    // ds_description
    let ds_description_sql = get_ddl("project-ds-description")?;
    _execute_sql(ds_description_sql.as_str(), &db).await?;

    Ok(())
}

/// 初始化一个项目 (完整流程)
pub async fn init_full(base_dir: &String) -> Result<(), AppError> {
    // 检查路径下是否已经存在项目
    let is_exit = check_full(base_dir).await?;
    if is_exit {
        log::error!("目标路径已存在项目, 初始化终止 {}", base_dir);
        return Err(AppError::Custom(
            "目标路径已存在项目，若要覆盖请清空后重试".to_string(),
        ));
    }

    // 创建或加载数据库
    create_or_load(&base_dir).await?;

    // 设置项目路径
    update_project_base_dir(base_dir.clone());

    // 执行初始化逻辑
    init_step().await?;
    log::info!("已完成项目初始化 {}", base_dir);

    Ok(())
}

/// 载入一个项目 (完整流程)
pub async fn load_full(base_dir: &String) -> Result<(), AppError> {
    // 路径检查
    let is_exit = check_full(base_dir).await?;
    if !is_exit {
        log::error!("加载项目错误，配置数据库不存在！");
        return Err(AppError::Custom(
            "无效的项目路径！请检查路径输入是否有误或在该目录下重新创建项目！".to_string(),
        ));
    }
    // 创建或加载项目
    create_or_load(&base_dir).await?;

    // 设置项目路径
    update_project_base_dir(base_dir.clone());

    log::info!("已完成项目加载 {}", base_dir);
    Ok(())
}
